package com.plian.system.service.qg.subsidiary.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.plian.Tools.*;
import com.plian.Tools.pagedata.PageData;
import com.plian.system.cache.DictCache;
import com.plian.system.cache.UserCache;
import com.plian.system.common.status.CheckStatus;
import com.plian.system.constant.sys.FormStatusConstant;
import com.plian.system.constant.sys.FormTypeConstant;
import com.plian.system.constant.yth.YthConstant;
import com.plian.system.entity.pm.property.PropertyRecord;
import com.plian.system.entity.qg.subsidiary.MixedOwnershipStructure;
import com.plian.system.entity.qg.subsidiary.SubsidiaryMixedReform;
import com.plian.system.entity.sys.ApprovalMessage;
import com.plian.system.enumeratea.ReformStatus;
import com.plian.system.mapper.qg.subsidiary.SubsidiaryMixedReformMapper;
import com.plian.system.mybatis.base.BaseFlowService;
import com.plian.system.mybatis.base.BaseServiceImpl;
import com.plian.system.service.pm.property.IPropertyRecordService;
import com.plian.system.service.qg.subsidiary.IMixedOwnershipStructureService;
import com.plian.system.service.qg.subsidiary.ISubsidiaryMixedReformOutService;
import com.plian.system.service.sys.code.IFormCodeService;
import com.plian.system.service.sys.file.FileService;
import com.plian.system.service.sys.message.IApprovalMessageService;
import com.plian.system.service.wf.FormWorkflowService;
import com.plian.system.vo.qg.subsidiary.SubsidiaryMixedReformVO;
import com.plian.system.vo.yth.YthResult;
import com.plian.system.wrapper.qg.subsidiary.SubsidiaryMixedReformWrapper;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

import static com.plian.system.constant.sys.ApprovalMessageTypeConstant.KT_TYPE;
import static com.plian.system.constant.sys.ApprovalMessageTypeConstant.REFORM_OUT;
import static com.plian.system.constant.sys.FormStatusConstant.UNREVIEWED;

@Slf4j
@Service
@AllArgsConstructor
public class SubsidiaryMixedReformOutServiceImpl extends BaseServiceImpl<SubsidiaryMixedReformMapper, SubsidiaryMixedReform> implements ISubsidiaryMixedReformOutService, BaseFlowService {

    private FileService fileService;
    private FormWorkflowService formWorkflowService;
    private IFormCodeService formCodeService;
    private SubsidiaryMixedReformWrapper subsidiaryMixedReformWrapper;
    private IMixedOwnershipStructureService mixedOwnershipStructureService;
    private IApprovalMessageService approvalMessageService;
    private IPropertyRecordService propertyRecordService;

    @Override
    public boolean saveOrUpdate(SubsidiaryMixedReform subsidiaryMixedReform) {
        boolean flag = false;
        if (subsidiaryMixedReform.getId() == null) {
            flag = true;
            subsidiaryMixedReform.setCode(formCodeService.getCode(FormTypeConstant.QG_SUBSIDIARY_OUT_FORM));
            subsidiaryMixedReform.setFormType(String.valueOf(FormTypeConstant.QG_SUBSIDIARY_OUT_FORM));
            subsidiaryMixedReform.setVersion(subsidiaryMixedReform.getVersion() + 1);
            subsidiaryMixedReform.setIsLatest(1);
            subsidiaryMixedReform.setReformStatus(ReformStatus.OUT_AUDIT.getStatus());
            updateReformStatus(subsidiaryMixedReform.getInitialId(), ReformStatus.OUT_AUDIT.getStatus());
        }

        if (subsidiaryMixedReform.getOutType() == null) {
            subsidiaryMixedReform.setOutType(2);
        }

        boolean result = super.saveOrUpdate(subsidiaryMixedReform);
        if (flag) {
            fileService.saveAll(String.valueOf(subsidiaryMixedReform.getId()), subsidiaryMixedReform.getDocList());
        } else {
            fileService.edit(String.valueOf(subsidiaryMixedReform.getId()), subsidiaryMixedReform.getDocList());
        }

        return result;
    }

    @Override
    public boolean deleteLogic(List<Long> ids) {
        for (Long id : ids) {
            SubsidiaryMixedReform subsidiaryMixedReform = getById(id);
            if (subsidiaryMixedReform == null) {
                return false;
            } else if (subsidiaryMixedReform.getStatus() != null &&
                    (subsidiaryMixedReform.getStatus() != FormStatusConstant.STASH && subsidiaryMixedReform.getStatus() != FormStatusConstant.UNREVIEWED)) {
                return false;
            }
            updateReformStatus(subsidiaryMixedReform.getInitialId(), ReformStatus.ADJUSTABLE.getStatus());
            formWorkflowService.deleteProcessInstance(String.valueOf(id));
            update(Wrappers.<SubsidiaryMixedReform>lambdaUpdate()
                    .eq(SubsidiaryMixedReform::getInitialId, subsidiaryMixedReform.getInitialId())
                    .eq(SubsidiaryMixedReform::getVersion, subsidiaryMixedReform.getVersion() - 1)
                    .set(SubsidiaryMixedReform::getIsLatest, 2));
        }
        boolean result = super.deleteLogic(ids);
        mixedOwnershipStructureService.deleteLogicByMixedReformId(ids);
        return result;
    }

    @Override
    public HashMap<String, Object> commit(String id) {
        handleStatus(Long.valueOf(id), FormStatusConstant.FLOW, null);

        //将需要提交的流程变量返回，用于工作流侧
        return new HashMap<String, Object>();
    }

    @Override
    public Boolean finish(String id) {
        /**
         * 设置审批人和审批时间
         */
        SubsidiaryMixedReform subsidiaryMixedReform = getById(id);
        updateReformStatus(subsidiaryMixedReform.getInitialId(), ReformStatus.OUT.getStatus());
        updateIsLatest(subsidiaryMixedReform.getInitialId());

        subsidiaryMixedReform.setApprovedUser(TokenUtil.getTokenUserId());
        Date now = DateUtil.now();
        subsidiaryMixedReform.setApprovedTime(now);
        subsidiaryMixedReform.setIsLatest(2);
        subsidiaryMixedReform.setReformStatus(ReformStatus.OUT.getStatus());
        updateById(subsidiaryMixedReform);

        return handleStatus(Long.valueOf(id), FormStatusConstant.FINISH, "审批完成");
    }

    @Override
    public Boolean reject(String id, int formState, String comment) {
        return handleStatus(Long.valueOf(id), formState, comment);
    }

    @Override
    public List<PageData> findByIds(List<String> formIds) {
        LambdaQueryWrapper<SubsidiaryMixedReform> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(SubsidiaryMixedReform::getId, Func.toLongList(StringUtils.join(formIds, StringPool.COMMA)));
        List<SubsidiaryMixedReform> subsidiaryMixedReformList = list(queryWrapper);
        List<SubsidiaryMixedReformVO> subsidiaryMixedReformVOS = subsidiaryMixedReformWrapper.entityToVO(subsidiaryMixedReformList);
        List<PageData> pageDataList = new ArrayList<>();
        try {
            if (CollectionUtil.isNotEmpty(subsidiaryMixedReformVOS)) {
                for (SubsidiaryMixedReformVO vo : subsidiaryMixedReformVOS) {
                    PageData pd = new PageData();
                    pd.put("id", vo.getId());
                    pd.put("UNITNAME", vo.getMixedEnterpriseName());
                    pd.put("APPLICANTNAME", vo.getCreateUserName());
                    pd.put("applicantId", vo.getCreateUser());
                    pd.put("applyOrganizationId", vo.getMixedEnterpriseId());
                    pd.put("formType", FormTypeConstant.QG_SUBSIDIARY_OUT_FORM);
                    pd.put("orgName", vo.getMixedEnterpriseName());
                    pageDataList.add(pd);
                }
            }

            return pageDataList;
        } catch (Exception e) {
            log.error(ExceptionUtils.getFullStackTrace(e));
        }
        return pageDataList;
    }

    @Override
    public List<Integer> getFormType() {
        return Arrays.asList(FormTypeConstant.QG_SUBSIDIARY_OUT_FORM);
    }


    @Override
    public void goBackToStash(String formId) {
        Long id = Long.valueOf(formId);
        SubsidiaryMixedReform subsidiaryMixedReform = getById(id);
        if (subsidiaryMixedReform.getStatus() == FormStatusConstant.FINISH) {
            LambdaUpdateWrapper<SubsidiaryMixedReform> updateWrapper = new LambdaUpdateWrapper<>();
            update(updateWrapper.eq(SubsidiaryMixedReform::getId, id)
                    .set(SubsidiaryMixedReform::getApprovedUser, null).set(SubsidiaryMixedReform::getApprovedTime, null));
            updateReformStatus(subsidiaryMixedReform.getInitialId(), ReformStatus.OUT_AUDIT.getStatus());
            updateIsLatest(subsidiaryMixedReform.getInitialId());
            List<SubsidiaryMixedReform> subsidiaryMixedReformList = list(new LambdaQueryWrapper<SubsidiaryMixedReform>()
                    .eq(SubsidiaryMixedReform::getInitialId, id)
                    .orderByDesc(SubsidiaryMixedReform::getVersion));
            if (CollectionUtil.isNotEmpty(subsidiaryMixedReformList) && subsidiaryMixedReformList.size() > 1) {
                SubsidiaryMixedReform property = subsidiaryMixedReformList.get(1);
                property.setIsLatest(2);
                updateById(property);
            }
        }

        handleStatus(Long.valueOf(formId), UNREVIEWED, null);
    }

    @Override
    public void propertyRefer(PageData propertyOut) {
        PropertyRecord propertyRecord = propertyRecordService.getById(propertyOut.getString("proId"));
        SubsidiaryMixedReform lastInfoVO = getOne(Wrappers.<SubsidiaryMixedReform>lambdaQuery()
                .eq(SubsidiaryMixedReform::getMixedEnterpriseId, propertyRecord.getInitialId())
                .eq(SubsidiaryMixedReform::getIsLatest, 2));
        if (lastInfoVO == null) {
            return;
        }
        if (lastInfoVO.getFormType().equals(String.valueOf(FormTypeConstant.QG_SUBSIDIARY_OUT_FORM))) {
            return;
        }
        List<MixedOwnershipStructure> ownershipStructures = mixedOwnershipStructureService.list(Wrappers.<MixedOwnershipStructure>lambdaQuery()
                .eq(MixedOwnershipStructure::getMixedReformId, lastInfoVO.getId()));
        lastInfoVO.setUnitRankId(propertyRecord.getOrgGradation());
        lastInfoVO.setMajorIndustryId(propertyRecord.getMajorIndustries());
        lastInfoVO.setAffiliatedOrgFullName(propertyRecord.getAffiliatedOrgFullName());
        lastInfoVO.setFunctionalCategoryId(propertyRecord.getFunctionalCategoryName());
        lastInfoVO.setMixedCategoryId(propertyRecord.getOrgCategory());
        lastInfoVO.setStateFundedRelation(propertyRecord.getStateFundedRelation());
        lastInfoVO.setRegisteredCapital(BigDecimalUtil.toBigdecimal(propertyRecord.getRegCapital()));
        lastInfoVO.setOutReason(DictCache.dictCodeListToName(propertyOut.getString("outReason")));
        lastInfoVO.setOutTime(DateUtil.now());
        lastInfoVO.setVersion(lastInfoVO.getVersion() + 1);
        lastInfoVO.setLastVersionId(lastInfoVO.getId());
        lastInfoVO.setCode(formCodeService.getCode(FormTypeConstant.QG_SUBSIDIARY_OUT_FORM));
        lastInfoVO.setFormType(String.valueOf(FormTypeConstant.QG_SUBSIDIARY_OUT_FORM));
        lastInfoVO.setIsLatest(2);
        lastInfoVO.setStatus(3);
        lastInfoVO.setOutType(1);
        lastInfoVO.setReformStatus(ReformStatus.OUT.getStatus());
        updateReformStatus(lastInfoVO.getInitialId(), ReformStatus.OUT.getStatus());
        lastInfoVO.setId(null);
        updateIsLatest(lastInfoVO.getInitialId());
        super.saveOrUpdate(lastInfoVO);

        if (CollectionUtil.isNotEmpty(ownershipStructures)) {
            for (MixedOwnershipStructure mixedOwnershipStructure : ownershipStructures) {
                mixedOwnershipStructure.setId(null);
                mixedOwnershipStructure.setMixedReformId(lastInfoVO.getId());
            }
            mixedOwnershipStructureService.saveList(ownershipStructures);
        }

    }

    /**
     * 统一处理状态机事件方法
     *
     * @param id           主键
     * @param updateStatus 更新状态
     * @param comment
     * @return boolean
     */
    private Boolean handleStatus(Long id, int updateStatus, String comment) {
        try {
            SubsidiaryMixedReform subsidiaryMixedReform = getById(id);
            subsidiaryMixedReform.setStatus(updateStatus);
            if (StringUtil.isNotBlank(subsidiaryMixedReform.getDataSource()) &&
                    StringUtil.isNotBlank(subsidiaryMixedReform.getDataSourceId())) {
                if (updateStatus == FormStatusConstant.FINISH || updateStatus == FormStatusConstant.REJECT) {
                    ApprovalMessage approvalMessage = new ApprovalMessage();
                    approvalMessage.setDataSourceId(subsidiaryMixedReform.getDataSourceId());
                    approvalMessage.setType(REFORM_OUT);
                    approvalMessage.setOpinion(comment);
                    approvalMessage.setIsApprove(updateStatus == FormStatusConstant.FINISH ? 2 : 1);
                    approvalMessage.setIsSend(1);
                    approvalMessage.setDataSourceType(KT_TYPE);
                    if (subsidiaryMixedReform.getDataSource().equals(YthConstant.DATA_NINGBO)) {
                        approvalMessage.setDataSourceType(YthConstant.DATA_NINGBO);
                        approvalMessage.setFilingUserName(UserCache.userIdToName(TokenUtil.getTokenUserId()));
                        approvalMessage.setFormType(FormTypeConstant.QG_SUBSIDIARY_OUT_FORM);
                        approvalMessage.setFilingCode(subsidiaryMixedReform.getCode());
                    }
                    approvalMessageService.save(approvalMessage);
                }
            }
            updateById(subsidiaryMixedReform);
            return true;
        } catch (Exception e) {
            log.error(ExceptionUtils.getFullStackTrace(e));
            return false;
        }
    }

    @Override
    public boolean submit(SubsidiaryMixedReform subsidiaryMixedReform) {
        if (!Optional.ofNullable(subsidiaryMixedReform.getStatus()).isPresent()) {
            subsidiaryMixedReform.setStatus(FormStatusConstant.UNREVIEWED);
        }
        if (CollectionUtil.isNotEmpty(subsidiaryMixedReform.getMajorIndustryIds())) {
            subsidiaryMixedReform.setMajorIndustryId(String.join(StringPool.COMMA, subsidiaryMixedReform.getMajorIndustryIds()));
        }
        if (CollectionUtil.isNotEmpty(subsidiaryMixedReform.getMixedModeIds())) {
            subsidiaryMixedReform.setMixedModeId(String.join(StringPool.COMMA, subsidiaryMixedReform.getMixedModeIds()));
        }

        boolean result = saveOrUpdate(subsidiaryMixedReform);
        if (result) {
            List<MixedOwnershipStructure> mixedOwnershipStructures = subsidiaryMixedReform.getMixedOwnershipStructures();
            if (CollectionUtil.isNotEmpty(mixedOwnershipStructures)) {
                for (MixedOwnershipStructure mixedOwnershipStructure : mixedOwnershipStructures) {
                    if (mixedOwnershipStructure.getId() != null &&
                            Optional.ofNullable(mixedOwnershipStructure.getIsDeleted()).isPresent() && mixedOwnershipStructure.getIsDeleted().intValue() == 1) {
                        mixedOwnershipStructureService.removeById(mixedOwnershipStructure.getId());
                    } else {
                        mixedOwnershipStructure.setMixedReformId(subsidiaryMixedReform.getId());
                        mixedOwnershipStructureService.saveOrUpdate(mixedOwnershipStructure);
                    }
                }
            }
        }
        HashMap<String, Object> processVariable = new HashMap<>();
        formWorkflowService.startProcessAndSimulate(String.valueOf(subsidiaryMixedReform.getId()), subsidiaryMixedReform.getFormType(), processVariable);
        return result;
    }

    private void updateReformStatus(Long initialId, int reformStatus) {
        update(new LambdaUpdateWrapper<SubsidiaryMixedReform>().eq(SubsidiaryMixedReform::getInitialId, initialId).set(SubsidiaryMixedReform::getReformStatus, reformStatus));
    }

    private void updateIsLatest(Long initialId) {
        update(new LambdaUpdateWrapper<SubsidiaryMixedReform>().eq(SubsidiaryMixedReform::getInitialId, initialId)
                .eq(SubsidiaryMixedReform::getIsLatest, 2).set(SubsidiaryMixedReform::getIsLatest, 1));
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public String saveOutMixedreforms(String data) {
        YthResult ythResult = new YthResult();
        //成功的id集合
        List<String> successIds = new ArrayList<>();
        //失败的id集合
        List<String> failIds = new ArrayList<>();
        //失败的原因
        List<String> failReasons = new ArrayList<>();
        //将json字符串转换成list
        List<SubsidiaryMixedReform> dataList = JSON.parseArray(data, SubsidiaryMixedReform.class);
        if (CollectionUtil.isNotEmpty(dataList)) {
            //根据datasourceIds 查询出所有的数据
            List<SubsidiaryMixedReform> list = list(new LambdaQueryWrapper<SubsidiaryMixedReform>().in(SubsidiaryMixedReform::getDataSourceId, dataList.stream().map(SubsidiaryMixedReform::getDataSourceId).toArray()));
            if (CollectionUtil.isNotEmpty(list)) {
                //删除子集
                List<Long> ids = list.stream().map(SubsidiaryMixedReform::getId).collect(Collectors.toList());
                mixedOwnershipStructureService.remove(new LambdaQueryWrapper<MixedOwnershipStructure>().in(MixedOwnershipStructure::getMixedReformId, ids));
            }
            //如果数据库中有数据，就更新，没有就新增
            for (SubsidiaryMixedReform entity : dataList) {
                //id重复略过
                if (CollectionUtil.isNotEmpty(list)) {
                    List<String> olIds = list.stream().map(SubsidiaryMixedReform::getDataSourceId).collect(Collectors.toList());
                    String dataSourceId = entity.getDataSourceId();
                    //判断数据库中是否有数据
                    if (olIds.contains(dataSourceId)) {
                        for (SubsidiaryMixedReform oldEntity : list) {
                            if (dataSourceId.equals(oldEntity.getDataSourceId())) {
                                //判断status是否为0，如果是0，就更新，不是0，就不更新
                                if (CheckStatus.checkCode(oldEntity.getStatus())) {
                                    successIds.add(dataSourceId);
                                    entity.setId(oldEntity.getId());
                                    entity.setDataSource(YthConstant.DATA_NINGBO);
                                    if (Optional.ofNullable(oldEntity.getInitialId()).isPresent()) {
                                        entity.setInitialId(oldEntity.getInitialId());
                                    } else {
                                        entity.setInitialId(oldEntity.getId());
                                    }
                                    submit(entity);
                                    list.remove(oldEntity);
                                    break;
                                } else {
                                    failIds.add(dataSourceId);
                                    failReasons.add("dataSourceId:" + dataSourceId + "数据已提交且已经在流程中，无法更新");
                                    break;
                                }
                            }
                        }
                    } else {
                        //如果数据库中没有数据，就新增
                        entity.setDataSource(YthConstant.DATA_NINGBO);
                        submit(entity);
                        successIds.add(entity.getDataSourceId());
                    }
                } else {
                    //如果数据库中没有数据，就新增
                    entity.setDataSource(YthConstant.DATA_NINGBO);
                    submit(entity);
                    successIds.add(entity.getDataSourceId());
                }
            }
        } else {
            failReasons.add("数据为空");
        }
        ythResult.setSuccessIds(successIds);
        ythResult.setFailIds(failIds);
        ythResult.setFailReason(StringUtils.join(failReasons, ";"));
        //ythResult转换成json字符串
        return JSON.toJSONString(ythResult);
    }

}
